<template>
    <div>
        <div style="display: flex;">
            <el-input v-model="roomId" placeholder="Please input" />
            <el-button type="primary" @click="requestState">call</el-button>
        </div>
        <video ref="localV" autoplay loop style="height: 200px;width: 200px;"></video>
        <video ref="remoteV" autoplay loop style="height: 200px;width: 200px;"></video>
        <div style="display: flex;">
            <div @click="getPhoto" style="text-align: center;flex: 1;background-color: rgb(0, 17, 255);margin: 10px;color: #fff;">截图</div>
            <div @click="getVideo" style="text-align: center;flex: 1;background-color: rgb(0, 17, 255);margin: 10px;color: #fff;">录制</div>
            <div @click="closePhone" style="text-align: center;flex: 1;background-color: rgb(0, 17, 255);margin: 10px;color: #fff;">挂断</div>
        </div>
        <div v-if="imgList.length!==0" style="overflow-x: scroll;display: flex;">
            <img style="width: 100px;height: 100px;" v-for="(item,index) in imgList" :src="item" :key="index" alt="" srcset="">
        </div>
        <div v-if="videos.length!==0" style="overflow-x: scroll;display: flex;">
            <video autoplay loop controls style="width: 100px;height: 100px;" v-for="(it,index) in videos" :src="it" :key="index"></video>
        </div>
    </div>
</template>

<script setup lang="ts">
import { onUnmounted, ref } from 'vue';
import {userStore} from '../../../../store/index'
import io from 'socket.io-client'
import RecordRTC from "recordrtc";
import {ElMessage} from 'element-plus'
// data
const store = userStore()
let remoteV= ref<HTMLVideoElement>() 
let localV= ref<HTMLVideoElement>() 
let roomId = ref('123')
let pc:any;
let stream:any;
let configure ={ video: true,audio: true };
let imgList = ref([] as Array<any>)
let videos = ref([] as Array<any>)
let recorder:any;
// 帮助服务器找到ip和通信设备
var iceServers = {
    iceServers: [
        { urls: 'stun:stun.services.mozilla.com' },
        { urls: 'stun:stun.schlund.de' },
        { urls: 'stun:stun1.l.google.com:19302' }
    ]
}

// data-end

onUnmounted(()=>{
    socketio.emit('close',{
        from: store.userInfo.phone,
        to: roomId.value,
    })
    if(stream){
        stream.getTracks().forEach((track:any)=>{
        track.stop()
    })
    }
})

// methods
// 请求查询对端是否在线
const requestState = ()=>{
    // 呼叫之前先检测对端是否在线
    socketio.emit('request',{
        from: store.userInfo.phone,
        to: roomId.value,
    })
}
// 对端在线后触发拨打电话事件
const call = async ()=>{
    console.log('对端号码',roomId.value);
    stream = await navigator.mediaDevices.getUserMedia(configure)
    console.log('接收到本端的媒体流', stream);
    if(localV.value){
        localV.value.srcObject = stream
    }
    stream.getTracks().forEach((track:any)=>{
        pc.addTrack(track,stream)
    })
    const offer = await pc.createOffer()
    await pc.setLocalDescription(offer)
    socketio.emit('offer',{
        from: store.userInfo.phone,
        to: roomId.value,
        offer
    })
}
//  连接成功触发
const connection = (message:any)=>{
    console.log("连接成功",message);
}
//  接收对端响应的offer信息，并保存后，创建answer信息发送给对端
const offer = async (data:any)=>{
    console.log("接收到了offer",data);
    await pc.setRemoteDescription(data.offer)
    // stream = await navigator.mediaDevices.getUserMedia(configure)
    stream = await navigator.mediaDevices.getDisplayMedia(configure)
    console.log('接收到本端的媒体流', stream);
    if(localV.value){
        localV.value.srcObject = stream
    }
    stream.getTracks().forEach((track:any)=>{
        pc.addTrack(track,stream)
    })
    const answer = await pc.createAnswer()
    await pc.setLocalDescription(answer)
    roomId.value = data.from
    socketio.emit('answer',{
        from: store.userInfo.phone,
        to: data.from,
        answer
    })
}
// 接收对端响应的answer信息，并保存到peerConnection对象中
const answer = async (data:any)=>{
    await pc.setRemoteDescription(data.answer)
}
// 接收服务器响应的对端不在线信息
const failFunction = (data:any)=>{
    console.log(data);
    ElMessage.error(data.msg)
}
//  接收服务响应的对端在线信息
const successFunction = (data:any)=>{
    console.log(data);
    call()
}
//  接收对端的媒体流（在对端使用peerConnection添加track触发）
const OnTrackFunction = async (event:any)=>{
    console.log('接收到对端的媒体流', event.streams[0]);
    if (event.streams[0] && event.streams[0].getTracks().length > 0) {
        // 包含轨道
        console.log('包含轨道');        
    } else {
        // 不包含轨道
        console.log('不包含轨道');
    }
    // 显示其他用户的视频流 -> 如果有指定房间人数,是否可以创建视频,然后动态显示窗口 
    // 接收视频流
    if (event.streams && event.streams[0]) {
        if(remoteV.value){
            remoteV.value.srcObject = event.streams[0]; // 如果对端发送了流，将其设置到远程视频元素中
        }
        console.log('对端已发送流');
    } else {
        console.log('对端未发送流');
    }
}
//  获取本端的candidate信息，发送给远端
const onicecandidate = (event:any)=>{
    console.log('onicecandidate',event);
    socketio.emit('candidate',{
        candidate: event.candidate,
        from: store.userInfo.phone,
        to: roomId.value,
    })
}
// 接收对端端的公网地址信息，添加到peerConection对象中保存
const candidate = (data:any)=>{
    if(data.candidate){
        const candidateValue = new RTCIceCandidate(data.candidate)
        pc.addIceCandidate(candidateValue)
    }
}
// 接收到对端挂断电话的信令
const hangUp = (data:any)=>{
    console.log("接收到挂断电话的信令",data);
    if(localV.value?.srcObject){
        const st:any = localV.value?.srcObject
        st.getTracks().forEach((track:any)=>{
            track.stop()
    })
    }
    if(remoteV.value?.srcObject){
        const st:any = remoteV.value?.srcObject
        st.getTracks().forEach((track:any)=>{
            track.stop()
    })
    }
    // 关闭对等连接
    pc.close() 

}

// 视频录制
const getVideo = ()=>{
    console.log("获取视频");
    startRecord()
}
//  挂断电话
const closePhone = ()=>{
    console.log("挂断电话"); 
    socketio.emit('hangUp',{
        from: store.userInfo.phone,
        to: roomId.value,
    })
}
// 录制视频
function startRecord() {
    const video = localV.value as HTMLVideoElement
    recorder = new RecordRTC(video.srcObject, {
    type: "video",
    canvas: {
        width: screen.availWidth,
        height: screen.availHeight / 3,
    },
    });
    recorder.startRecording();
    setTimeout(() => {
    stopRecord();
    }, 3000);
}
function stopRecord() {
    if (recorder) {
    recorder.stopRecording(() => {
        const blob = recorder.getBlob();
        const url = URL.createObjectURL(blob);
        videos.value.push(url);
    });
    }
}
// 视频截图
const getPhoto = ()=>{
    const canvas = document.createElement('canvas')
    if(localV.value){
        canvas.width = localV.value.videoWidth
        canvas.height = localV.value.videoHeight
        const ctx = canvas.getContext('2d')
        if(ctx){
            ctx.drawImage(localV.value, 0, 0, canvas.width, canvas.height)
            console.log('🚀🚀🚀 / imgList', canvas.toDataURL('image/png'))
            imgList.value.push(canvas.toDataURL('image/png'))
        }
    }
    
}

// methods-end

// socket event Listen 
const socketio = io(`http://${location.hostname}:9001`,{
    query: {
        userid: store.userInfo.phone
    }
})

socketio.on('connection',connection)
socketio.on('offer',offer)
socketio.on('answer',answer)
socketio.on('fail',failFunction)
socketio.on('success',successFunction)
socketio.on('candidate',candidate)
socketio.on('hangUp',hangUp)

pc = new RTCPeerConnection(iceServers) 
pc.onicecandidate = onicecandidate // 双方连接后,注册candidate
pc.ontrack = OnTrackFunction

</script>

<style scoped>

</style>